package com.cskaoyan.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * @Author Pudding
 * @Date 2024/6/14 14:16
 */
@Configuration
public class ShiroConfiguration {

    //1. ShiroFilter在SpringBoot应用中ShiroFilter只需要注册到容器中就会生效 → 可以引用容器中的其他组件
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();

        /*
        ShiroFilter提供的FilterChain
            anon：匿名Filter，作用范围内的请求不需要认证和授权
            authc：isAuthenticated为true才能通过 → 这个值怎么才能变为true → 需要登录，需要写登录请求
            perms：hasPermission 为true才能通过
        */
        //1.1 过滤器是有序的 → 提供的Map里的键值对也是有序的 → LinkedHashMap
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // Map的key：请求的URI(可以使用通配符)、Map的value：过滤器的名称
        filterChainDefinitionMap.put("/wx/home/*", "anon");
        filterChainDefinitionMap.put("/wx/goods/*", "anon");
        filterChainDefinitionMap.put("/wx/auth/*", "anon");
        filterChainDefinitionMap.put("wx/brand/*", "anon");
        filterChainDefinitionMap.put("wx/issue/*", "anon");
        filterChainDefinitionMap.put("/wx/cart/goodscount", "anon");
        filterChainDefinitionMap.put("/wx/cart/*", "authc");
        filterChainDefinitionMap.put("wx/collect/*", "authc");
        filterChainDefinitionMap.put("wx/address/*", "authc");
        filterChainDefinitionMap.put("wx/aftersale/*", "authc");
        //给orderlist上锁，通过realm获取钥匙
        filterChainDefinitionMap.put("/wx/order/list", "perms[orderlist]");

        //1.2 如果没有登录的话，它会重定向到 /login.jsp，如果我们要修改重定向的地址，通过开发handler响应一段JSON字符串
        filterFactoryBean.setLoginUrl("/wx/auth/unAuthc");

        //1.3 ShiroFilter中注入FilterChain
        filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        //1.4 ShiroFilter中注入安全管理
        filterFactoryBean.setSecurityManager(securityManager);

        return filterFactoryBean;
    }

    //2. 将SecurityManager注册为容器中的组件
    @Bean
    public DefaultWebSecurityManager securityManager(CustomRealm customRealm, DefaultWebSessionManager sessionManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //2.1 设置认证器，但是你可以不设置，它会给你提供一个默认的认证器(ModularRealmAuthenticator)
        //securityManager.setAuthenticator();

        //2.2 设置授权器，但是你可以不设置，它会给你提供一个默认的授权器(ModularRealmAuthorizer)
        //securityManager.setAuthorizer();

        //2.3 给默认的认证器和授权器，提供realm
        securityManager.setRealm(customRealm);
        securityManager.setSessionManager(sessionManager);

        return securityManager;
    }

    //3. Shiro提供了SessionManager用来管理Session
    // 要想拿到原来的subject，要保证使用同一个session
    // SessionManager要保证访问认证的请求使用的是同一个Session，那么他们的SessionId要相同
    @Bean
    public DefaultWebSessionManager sessionManager(){
        return new CustomSessionManager();
    }

}
